package com.woniuxy.house.filter;

import cn.hutool.core.exceptions.ValidateException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.woniuxy.house.entity.JwtToken;
import com.woniuxy.house.utils.JwtUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;

import java.util.ArrayList;
import java.util.List;

/**
 * 定制自定义逻辑，查数据库得到用户
 * <p>
 * 覆盖springsecurity的默认实现，根据表单提交的账户，得到用户的信息，封装给SpringSecurity进行验证
 *
 * @author baobo
 * @date 2022-08-17-19:59
 */
@Slf4j
public class JwtAuthenticationProvider implements AuthenticationProvider {

	@Autowired
	private JwtUtil jwtUtil;
	@Autowired
	private ObjectMapper objectMapper;

	@Override
	public Authentication authenticate(Authentication authentication) throws AuthenticationException {
		JwtToken jwtToken = (JwtToken) authentication;
		String jwt = (String) jwtToken.getPrincipal();

		if (jwt == null ||!jwtUtil.verifyJWT(jwt)) {
			throw new ValidateException("令牌无效");
		}
		//jwtUtil.
		List<SimpleGrantedAuthority> authorities = new ArrayList<>();
		SimpleGrantedAuthority simpleGrantedAuthority = new SimpleGrantedAuthority("all");
		authorities.add(simpleGrantedAuthority);
		//产生已认证通过的JwtToken
		JwtToken authenticatedToken = new JwtToken(jwt, true, authorities);
		//保存起来
		SecurityContextHolder.getContext().setAuthentication(authenticatedToken);
		return authenticatedToken;

	}


	/**
	 * 确定此 Class 对象表示的类或接口是否与指定的 Class 参数表示的类或接口相同，或者是其超类或超接口。
	 * 如果是，则返回 true；
	 * 否则返回false。如果此 Class 对象表示原始类型，则如果指定的 Class 参数正是此 Class 对象，
	 * 则此方法返回 true；否则返回false。
	 *
	 * @param authentication
	 * @return
	 */
	@Override
	public boolean supports(Class<?> authentication) {
		boolean assignableFrom = JwtToken.class.isAssignableFrom(authentication);

		return assignableFrom;
	}
}
